package ClientDB;
import java.util.*;

import java.io.*;
import java.net.*;

import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.StyledText;
import org.eclipse.swt.custom.TableEditor;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.layout.FormAttachment;
import org.eclipse.swt.layout.FormData;
import org.eclipse.swt.layout.FormLayout;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.List;
import org.eclipse.swt.widgets.MessageBox;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.TableItem;
import org.eclipse.swt.widgets.Text;
import DataConnectionInterface.*;

public class SelectFantasyUniverseGUI {

    private Shell shell;
    private Button goToGame;
    private Button returnToMain;
    private Button highscores;
    private Image background;
    private List playersList;
    private Text playersText;
    private boolean playersUniverseSelectedFlag;
    private Font font;
    private Font listFont;
    private String playersUniverseString;
    
    private ArrayList<String> worldList = new ArrayList<String>();
    private ArrayList<Card> cardsList = new ArrayList<Card>();
    private ArrayList<UserInfo> usersList = new ArrayList<UserInfo>();

    private ObjectInputStream in = null;
    private ObjectOutputStream out = null;
    private Socket client = null;
    
    private boolean playerArrived = false;
    private boolean playerBegins = false;
    private boolean waiting = false;
   
    
    public SelectFantasyUniverseGUI(Shell shell, ObjectInputStream in, ObjectOutputStream out, Socket client) {
    	
		this.in = in;
		this.out = out;
    	this.client = client;
    	
		// get list of worlds from server (from databases)
    	try{
    		
		String world;
		Integer worldSize = (Integer) in.readObject();
		for(int i = 0;i < worldSize;i++){
			world = (String) in.readObject();
			worldList.add(world);
		}
		
    	} catch(IOException e){
    		
    	} catch (ClassNotFoundException e) {
			
		}
    	
        FormLayout layout = new FormLayout();
        this.shell = shell;
        this.background = new Image(shell.getDisplay(), "select.jpg");
        this.font = new Font(shell.getDisplay(), "Monotype Corsiva", 14, SWT.ITALIC);
        this.listFont = new Font(shell.getDisplay(), "Monotype Corsiva", 12, SWT.ITALIC);
        shell.setBackgroundImage(background);
        shell.setBounds(background.getBounds());
        shell.setText("Universe Selecetion");
        shell.setLocation(5, 5);
        shell.setLayout(layout);
        createButtons();
        addButtonListeners();
        initButtonToolTips();
        initFlags();
        createLists();
        addListListeners();
        addText();
	    
    }
    
    private void highscoresButtonLogic() {
    	usersList.clear();
    	try {
			out.writeObject(new String("HIGH SCORES"));
			int numOfUsers = 20;
			// get the user's high scores
			out.writeObject(new Integer(numOfUsers));
			numOfUsers = (Integer) in.readObject();
			
			for(int i = 0;i < numOfUsers;i++){
				UserInfo user = (UserInfo) in.readObject();
				usersList.add(user);	
			}
			
		} catch (IOException e) {
			
		} catch (ClassNotFoundException e) {
			
		} 
		
        new DialogHighscores();

    }

    private void waitForPlayers() {
    	waiting = true;
    	final Display display = Display.getDefault();
    	final Shell shell = new Shell(display, SWT.BORDER);
        new WaitWindow(shell, out);
        
        shell.setSize(350, 150);
        shell.open();
        
        // open thread for waiting
        Thread listen = new Thread(new Runnable(){
        	
        	@Override
        	public void run() {
        		playerArrived = false;
        		
        		try {
        					
        			boolean proceedToGame = (Boolean) in.readObject();
        			if(proceedToGame){
						playerBegins = (Boolean) in.readObject(); 
						playerArrived = true;
        			}
        			
        			
				} catch (IOException e) {
					
				} catch (ClassNotFoundException e) {
					
				}
				
				display.asyncExec(new Runnable(){

					@Override
					public void run() {
						shell.close();
						waiting = false;
						if(playerArrived) openGameGUI();
					}
					
				});
				
        	}
        });
        listen.start();
        
        while (!shell.isDisposed()) {
        	if (!display.readAndDispatch()) {
	            display.sleep();
	        }
	    }
        
	}


    private void populateLists(List list) {
    	// add all worlds to scroll list
    	Iterator<String> iter = worldList.iterator();
    	while(iter.hasNext())
    		list.add(iter.next());
    	
    }

    private void proceedToGameButtonLogic() {
    
    	try {
			out.writeObject(new String("NEW GAME"));
		} catch (IOException e1) {
		}
    	
    	Thread waitThread = new Thread(new Runnable(){

			@Override
			public void run() {
				try{
		    		// send to server the chosen world
					
		    		out.writeObject(new String(playersUniverseString));
					
		    		// receive cards from chosen world
		    		Card card;
		    		Integer deckSize = (Integer) in.readObject();
		    		for(int i = 0;i < deckSize;i++){
		    			card = (Card) in.readObject();
		    			cardsList.add(card);
		    		}
		    		
		    	} catch(IOException e){
		    		
		    	} catch (ClassNotFoundException e) {
					
				}
		    	
		    	// wait for player to join
		    	waitForPlayers();
			}
    		
    	});
    	Display.getCurrent().syncExec(waitThread);
    	
    }

    private void openGameGUI() {
    	// close select-world window
    	shell.close();
    	
    	// open game window
    	Display display = Display.getCurrent();
    	shell = new Shell(display, SWT.NO_REDRAW_RESIZE);
        shell.setText("Fantasy card game");
        
        FillLayout layout = new FillLayout();
        shell.setLayout(layout);
        
        // should be new tmpBoard(shell, cardsList, playerBegins, in ,out);
        new Board(shell, cardsList, playerBegins, in ,out, client, playersUniverseString); 
        
        shell.setSize(900, 650);
        shell.setLocation(50, 50);
        shell.open();

        while (!shell.isDisposed()) {
        	if (!display.readAndDispatch()) {
        		display.sleep();
        	}
        }
    			
	}


	private void returnBackToMainButtonLogic() {
    	shell.close();
    	
    	try {
    		
			in.close();
			out.close();
	    	client.close();
	    	
		} catch (IOException e) {
			
		}
    	
		// go back to menu window
    	Display display = Display.getCurrent();
    	Shell shell = new Shell(display, SWT.MENU);
        new Menu(shell);
        shell.open();
        while (!shell.isDisposed()) {
        	if (!display.readAndDispatch()) {
        		display.sleep();
        	}
        }
       
    }

    private void initFlags() {
        this.playersUniverseSelectedFlag = false;
    }


    private FormData locateButton(int width, int height, int top1, int top2,
            int left1, int left2) {
        FormData result = new FormData(width, height);
        result.top = new FormAttachment(top1, top2);
        result.left = new FormAttachment(left1, left2);
        return result;
    }

    private void addButtonListeners() {
        goToGame.addSelectionListener(new SelectionListener() {
            public void widgetSelected(SelectionEvent e) {
            	if(waiting) return;
                if(playersUniverseSelectedFlag)
                    proceedToGameButtonLogic();
            }

            public void widgetDefaultSelected(SelectionEvent e) {
                
            }
        });
        returnToMain.addSelectionListener(new SelectionListener() {

            public void widgetSelected(SelectionEvent e) {
                returnBackToMainButtonLogic();
            }

            public void widgetDefaultSelected(SelectionEvent e) {
                
            }
        });
        highscores.addSelectionListener(new SelectionListener() {

            public void widgetSelected(SelectionEvent e) {
                highscoresButtonLogic();
            }

            public void widgetDefaultSelected(SelectionEvent e) {
            	
            }
        });
        
    }

    private void initButtonToolTips() {
        if (playersUniverseSelectedFlag) {
            goToGame.setToolTipText("Proceed to game");
        } else {
            goToGame.setToolTipText("First select the players universe to proceed");
        }
        returnToMain.setToolTipText("Go back to the Main menu");
        highscores.setToolTipText("View Highscores");
    }
    
    private void createButtons() {
    	
        this.goToGame = new Button(shell, SWT.FLAT);
        goToGame.setText("Start game");
        goToGame.setFont(font);
        FormData newGameFD = locateButton(160, 32, 10, 60, 39, 15);
        goToGame.setLayoutData(newGameFD);
        
        this.returnToMain = new Button(shell, SWT.FLAT);
        returnToMain.setText("Return to Main menu");
        returnToMain.setFont(font);
        FormData quitGameFD = locateButton(160, 32, 10, 93, 39, 15);
        returnToMain.setLayoutData(quitGameFD);
        
        this.highscores = new Button(shell, SWT.FLAT);
        highscores.setText("Highscores");
        highscores.setFont(font);
        FormData highscoresFD = locateButton(160, 32, 10, 127, 39, 15);
        highscores.setLayoutData(highscoresFD);

    }

    private void addText() {
    	this.playersText = new Text(shell, SWT.READ_ONLY | SWT.BOLD | SWT.BORDER);
        playersText.setFont(font);
        playersText.setText("Select Players universe:");
        playersText.setBounds(0, 0, 120, 25);

        FormData playersTextFD = locateButton(160, 26, 53, 6, 35, 15);
        //playersText.setBackground(new Color(shell.getDisplay(), 170, 240, 155));
        playersText.setBackground(new Color(shell.getDisplay(), 240, 230, 130));
        playersText.setLayoutData(playersTextFD);
    }

    private void addListListeners() {
        playersList.addSelectionListener(new SelectionListener() {
            public void widgetSelected(SelectionEvent e) {
                if(playersList.getSelectionCount() > 0) {
                     playersUniverseString =  playersList.getSelection()[0]; 
                     playersUniverseSelectedFlag = true;
                     initButtonToolTips();
                }
            }

            public void widgetDefaultSelected(SelectionEvent e) {
            
            }
        });
    }

    private void createLists() {
    	 this.playersList = new List(shell, SWT.SINGLE | SWT.V_SCROLL | SWT.BORDER);
         populateLists(playersList);
         FormData playersListDB = locateButton(200, 130, 61, 6, 35, 15);
         playersList.setLayoutData(playersListDB);
         playersList.setFont(listFont);
         playersList.setBackground(new Color(shell.getDisplay(), 240, 230, 130));     
    }
    
    private class DialogHighscores {

        private Table table;

        private void addItemToTable(String name, Integer num, String description) {
            TableItem item = new TableItem(table, SWT.NONE, 0);
            item.setText(0, name);
            item.setText(1, num.toString());
            Button clickButton = new Button(table, SWT.PUSH);
            clickButton.setText("Click for Details");
            clickButton.pack();
            TableEditor editor = new TableEditor(table);
            editor.minimumWidth = clickButton.getSize().x;
            editor.horizontalAlignment = SWT.CENTER;
            editor.setEditor(clickButton, item, 2);
            clickButton.setToolTipText(description);
            final String descriptionFinal = description;
            clickButton.addSelectionListener(new SelectionListener() {

                public void widgetSelected(SelectionEvent e) {
                    new DescriptionPopup(descriptionFinal);
                }

                public void widgetDefaultSelected(SelectionEvent e) {
                }
            });
        }

        private void fillTable() {
        	int size = usersList.size();
        	for(int i = 0;i < size;i++){
        		UserInfo user = usersList.get(size - i - 1);
        		addItemToTable(user.getName(), user.getWins(), user.getDescription());
        	}
        }

        private void initTable(Shell shell) {
            this.table = new Table(shell, SWT.MULTI | SWT.FULL_SELECTION | SWT.V_SCROLL);
            table.setLinesVisible(true);
            table.setHeaderVisible(true);
            table.setFont(font);

            String[] titles = {"Username", "Wins", "Description"};
            for (int i = 0; i < titles.length; i++) {
                TableColumn column = new TableColumn(table, SWT.NONE);
                column.setText(titles[i]);
            }
            for (int i = 1; i < titles.length; i++) {
                table.getColumn(i).pack();
            }
            table.getColumn(0).setWidth(100);
            table.getColumn(1).setWidth(80);
            table.getColumn(2).setWidth(130);
            fillTable();
        }

        private DialogHighscores() {
            Display display = shell.getDisplay();
            final Shell shell = new Shell(display, SWT.MENU);
            shell.setLayout(new FillLayout());
            shell.setText("Highscores Table");
            initTable(shell);
            shell.pack();
            shell.open();
            while (!shell.isDisposed()) {
                if (!display.readAndDispatch()) {
                    display.sleep();
                }
            }
        }

        private class DescriptionPopup {

            private StyledText descriptionText;

            // adds newlines so that the text is viewable
            private String formatDescription(String input) {
                String result = input;
                int len = input.length();
                for (int i = 50; i < len; i += 50) {
                    String end = result.substring(i);
                    result = result.substring(0, i) + "\n" + end;
                    len = result.length();
                }
                return result;
            }

            private DescriptionPopup(String descript) {
                Display display = shell.getDisplay();
                Shell shell = new Shell(display, SWT.MENU);
                shell.setLayout(new FillLayout());
                shell.setText("User Description");
                this.descriptionText = new StyledText(shell, SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL);
                String s = formatDescription(descript);
                descriptionText.setEnabled(false);
                descriptionText.setText(s);
                shell.pack();
                shell.setSize(200, 100);
                shell.open();
                while (!shell.isDisposed()) {
                    if (!display.readAndDispatch()) {
                        display.sleep();
                    }
                }
            }
        }
    }
    
}